package com.caption.cloud.intercaptor;


import com.caption.cloud.constant.HeaderConstant;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;


/**
 * @description: TODO
 * @author: 码农
 * @date: 2021-12-18 23:46:27
 */
@Slf4j
public class FeignBasicAuthInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {

        String name = requestTemplate.feignTarget().name();
        log.info("--------------feign调用,serviceName={}",name);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            String token = request.getHeader(HeaderConstant.TOKEN_HEADER);
            String traceId = request.getHeader(HeaderConstant.TRACE_ID_HEADER);
            String serviceName = request.getHeader(HeaderConstant.SERVICE_HEADER);
            //将请求客户端的token放到feign的调用请求头中，注意如果加上hystrix熔断之后 attributes为就会为空
            //因为hystrix默认阻隔策略是基于线程的，当需要访问其他服务时会默认开辟新执行的线程
            //所有请求线程和执行线程不是一个线程有两个threadLocal所以是RequestContextHolder是获取不到请求线程的对象
            //这个时候要么就改hystrix基于信号量进行阻隔策略但是官网不推荐，还有就是自定义hystrix熔断策略 将请求线程HttpServletRequest传给执行线程
            if (StringUtils.isNotBlank(token)) {
                requestTemplate.header(HeaderConstant.TOKEN_HEADER, token);
            }
            if (StringUtils.isNotBlank(traceId)) {
                requestTemplate.header(HeaderConstant.TRACE_ID_HEADER, traceId);
            }
            if (StringUtils.isNotBlank(serviceName)) {
                requestTemplate.header(HeaderConstant.SERVICE_HEADER, traceId);
            }
        }
    }
}